﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AppFindDevice
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }
        private void ShowLog(string message, Color color)
        {
            if (this.labelInfo.InvokeRequired)
            {
                this.labelInfo.Invoke(new Action(() =>
                {
                    ShowLog(message, color);
                }));
            }
            else
            {
                this.labelInfo.BackColor = color;
                this.labelInfo.ForeColor = Color.White;
                this.labelInfo.Text = message;
            }
        }
        private void EnableControls(bool visible)
        {
            if (this.buttonFind.InvokeRequired)
            {
                this.buttonFind.Invoke(new Action(() =>
                {
                    EnableControls(visible);
                }));
            }
            else
            {
                this.buttonFind.Enabled = visible;
                this.comboBoxDevices.Enabled = visible;
            }
        }
        private void InitFocus()
        {
            if (this.buttonFind.InvokeRequired)
            {
                this.buttonFind.Invoke(new Action(() =>
                {
                    InitFocus();
                }));
            }
            else
            {
                this.buttonFind.Focus();
                this.buttonFind.Select();
            }
        }
        private object GetSelectedItem()
        {
            object result = null;
            if (this.comboBoxDevices.InvokeRequired)
            {
                this.comboBoxDevices.Invoke(new Action(() =>
                {
                    result = GetSelectedItem();
                }));
            }
            else
            {
                result = this.comboBoxDevices.SelectedItem;
            }
            return result;
        }
        private void FormMain_Load(object sender, EventArgs e)
        {
            LoadDevices();
            InitFocus();
        }
        private void LoadDevices()
        {
            this.comboBoxDevices.Items.Clear();
            foreach (var d in DeviceInfo.Devices)
            {
                this.comboBoxDevices.Items.Add(d);
            }
            this.comboBoxDevices.SelectedIndex = 0;
        }
        private byte[] HexStringToByteArray(string hexString)
        {
            if (string.IsNullOrWhiteSpace(hexString))
            {
                throw new ArgumentNullException("十六进制字符串有误");
            }
            else
            {
                hexString = hexString.Replace(" ", "");
                int length = hexString.Length;
                if (length % 2 != 0)
                {
                    throw new ArgumentNullException("十六进制字符串有误");
                }
                else
                {
                    byte[] bytes = new byte[length / 2];
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                    return bytes;
                }
            }
        }
        private void buttonFind_Click(object sender, EventArgs e)
        {
            if (!this.checkBoxEnable.Checked)
            {
                FindByCom();
            }
            else
            {
                FindByTCP();
            }
        }
        private async void FindByCom()
        {
            await Task.Run(() =>
            {
                EnableControls(false);
                var ports = SerialPort.GetPortNames();

                ShowLog("正在查找对应的设备......", Color.Gold);
                if (ports != null && ports.Length > 0)
                {
                    string portName = "";
                    var item = GetSelectedItem() as DeviceInfo;
                    if (item != null)
                    {
                        foreach (var port in ports)
                        {
                            ShowLog($"正在对串口：{port} 进行匹配", Color.Black);
                            SerialPort serialPort = null;
                            try
                            {
                                serialPort = new SerialPort(port);
                                serialPort.BaudRate = 9600;
                                serialPort.DataBits = 8;
                                serialPort.Parity = Parity.None;
                                serialPort.StopBits = StopBits.One;
                                serialPort.ReadTimeout = 500;
                                serialPort.WriteTimeout = 500;
                                serialPort.Open();
                                if (serialPort.IsOpen)
                                {
                                    if (!item.IsHex)
                                    {
                                        serialPort.Write(item.Command);
                                    }
                                    else
                                    {
                                        byte[] buffer = HexStringToByteArray(item.Command);
                                        serialPort.Write(buffer, 0, buffer.Length);
                                    }
                                    Thread.Sleep(100);
                                    byte[] data = new byte[1024];
                                    int dataLength = serialPort.Read(data, 0, data.Length);
                                    if (dataLength > 0)
                                    {
                                        portName = port;
                                        break;
                                    }
                                }
                            }
                            catch
                            {
                            }
                            finally
                            {
                                if (serialPort != null)
                                {
                                    try
                                    {
                                        serialPort.Close();
                                        serialPort.Dispose();
                                        serialPort = null;
                                    }
                                    catch { }
                                }
                            }
                        }
                        if (!string.IsNullOrWhiteSpace(portName))
                        {
                            ShowLog($"对应串口为：{portName}", Color.Green);
                        }
                        else
                        {
                            ShowLog("没有合适的串口", Color.Red);
                        }
                    }
                    else
                    {
                        ShowLog("没有合适的设备", Color.Red);
                    }
                }
                else
                {
                    ShowLog("本机没有任何串口", Color.Red);
                }
                EnableControls(true);
            });
        }
        private async void FindByTCP()
        {
            await Task.Run(() =>
            {
                EnableControls(false);
                var ports = SerialPort.GetPortNames();

                ShowLog("正在查找对应的设备......", Color.Gold);

                var item = GetSelectedItem() as DeviceInfo;
                if (item != null)
                {
                    string ip = this.textBoxIP.Text;
                    string port = this.textBoxPort.Text;
                    IPAddress ipValue = null;
                    int portValue = 0;
                    if (IPAddress.TryParse(ip, out ipValue) && int.TryParse(port, out portValue))
                    {
                        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        try
                        {
                            socket.ReceiveTimeout = 1000;
                            socket.ConnectAsync(ip, portValue).Wait(500);

                            if (socket.Connected)
                            {

                                if (!item.IsHex)
                                {
                                    socket.Send(Encoding.UTF8.GetBytes(item.Command));
                                }
                                else
                                {
                                    socket.Send(HexStringToByteArray(item.Command));
                                }


                                byte[] buffer = new byte[1024];
                                int length = socket.Receive(buffer);

                                if (length > 0)
                                {
                                    string content = Encoding.UTF8.GetString(buffer.Take(length).ToArray());
                                    ShowLog($"结果：{content}", Color.Green);
                                }
                                else
                                {
                                    ShowLog($"通讯异常", Color.Red);
                                }
                            }
                            else
                            {
                                ShowLog($"无法建立连接", Color.Red);
                            }
                        }
                        catch (Exception ex)
                        {
                            ShowLog($"发生错误：{ex.Message}", Color.Red);
                        }
                        finally
                        {
                            if (socket != null && socket.Connected)
                            {
                                socket.Close();
                                socket = null;
                            }
                        }
                    }
                    else
                    {
                        ShowLog($"IP或端口数据有误", Color.Red);
                    }
                }
                else
                {
                    ShowLog("没有合适的设备", Color.Red);
                }
                EnableControls(true);
            });
        }
        private void checkBoxEnable_CheckedChanged(object sender, EventArgs e)
        {
            bool tcpChecked = this.checkBoxEnable.Checked;
            this.textBoxIP.Enabled = tcpChecked;
            this.textBoxPort.Enabled = tcpChecked;
        }
    }
}
